package com.opdar.gulosity.event.other;

import com.opdar.gulosity.base.Constants;
import com.opdar.gulosity.base.MysqlContext;
import com.opdar.gulosity.connection.MysqlConnection;
import com.opdar.gulosity.connection.entity.Column;
import com.opdar.gulosity.connection.entity.SlaveEntity;
import com.opdar.gulosity.connection.protocol.HeaderProtocol;
import com.opdar.gulosity.error.ConnectionCloseException;
import com.opdar.gulosity.error.NotSupportBinlogException;
import com.opdar.gulosity.event.base.Event;
import com.opdar.gulosity.event.binlog.SlaveFetchEvent;
import com.opdar.gulosity.persistence.IPersistence;
import com.opdar.gulosity.utils.BufferUtils;
import com.opdar.gulosity.utils.MysqlUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Created by Shey on 2016/8/22.
 */
public class SlaveQueryEvent implements Event {
    private final MysqlConnection connection;
    private final Logger logger = LoggerFactory.getLogger(getClass());

    public SlaveQueryEvent(MysqlConnection connection) {
        this.connection = connection;
    }

    public void doing() {
        SlaveEntity slaveEntity = null;
        IPersistence persistence = MysqlContext.getPersistence();
        if(persistence != null && persistence.getFileName() != null){
            slaveEntity = new SlaveEntity();
            slaveEntity.setPosition((int) persistence.getPosition());
            slaveEntity.setFile(persistence.getFileName());
            slaveEntity.setSlaveId((int) connection.getAuthInfo().getServerId());
        }
        if(slaveEntity == null){
            querySlave(slaveEntity = new SlaveEntity());
        }

        //slave协议准备发送(binlog dump)

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        out.write((byte)  0x12);
        BufferUtils.writeInt(slaveEntity.getPosition(), out);

        int binlog_flags = 0;
        out.write(binlog_flags);
        out.write(0x00);
        BufferUtils.writeInt(slaveEntity.getSlaveId(), out);
        if (slaveEntity.checkBinlogFile()) {
            try {
                out.write(slaveEntity.getFile().getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


        try {
            byte[] array = out.toByteArray();
            HeaderProtocol header = new HeaderProtocol();
            header.setBodyLength(array.length);
            header.setSequence((byte) 0x00);
            connection.getChannel().write(new ByteBuffer[]{ByteBuffer.wrap(header.toBytes()),
                    ByteBuffer.wrap(array)});
            new SlaveFetchEvent(connection).doing();
        }catch (ConnectionCloseException e){
            throw e;
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void querySlave(SlaveEntity slaveEntity) {
        try{
            List<Map<Column, String>> result = MysqlUtils.query(connection.getChannel(), Constants.SHOW_MASTER_STATUS);
            if(result.size() > 0){

                {
                    Map<Column, String> map = result.get(0);
                    for(Iterator<Map.Entry<Column, String>> it = map.entrySet().iterator(); it.hasNext();){
                        Map.Entry<Column, String> column = it.next();
                        if(column.getKey().getName().equals(Constants.POSITION)){
                            slaveEntity.setPosition(Integer.valueOf(column.getValue()));
                        }
                        if(column.getKey().getName().equals(Constants.FILE)){
                            slaveEntity.setFile(column.getValue());
                        }
                    }
                }
                slaveEntity.setSlaveId((int) connection.getAuthInfo().getServerId());

            }else{
//                throw new NotSupportBinlogException("Master not support binlog.");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
